home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / polyobj.c < prev    next >
C/C++ Source or Header  |  1998-04-09  |  20KB  |  813 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/polyobj.c,v $
  15.  * $Revision: 1.2 $
  16.  * $Author: hfrieden $
  17.  * $Date: 1998/04/09 17:18:22 $
  18.  * 
  19.  * Hacked-in polygon objects
  20.  * 
  21.  * $Log: polyobj.c,v $
  22.  * Revision 1.2  1998/04/09 17:18:22  hfrieden
  23.  * Added code for ViRGE briefing
  24.  *
  25.  * Revision 1.1.1.1  1998/03/03 15:12:29  nobody
  26.  * reimport after crash from backup
  27.  *
  28.  * Revision 1.2  1998/02/28 00:40:16  tfrieden
  29.  * aga support
  30.  *
  31.  * Revision 1.1.1.1  1998/02/13  20:20:53  hfrieden
  32.  * Initial Import
  33.  *
  34.  */
  35.  
  36.  
  37. #pragma off (unreferenced)
  38. static char rcsid[] = "$Id: polyobj.c,v 1.2 1998/04/09 17:18:22 hfrieden Exp $";
  39. #pragma on (unreferenced)
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44.  
  45. #ifdef DRIVE
  46. #include "drive.h"
  47. #else
  48. #include "inferno.h"
  49. #endif
  50.  
  51. #include "polyobj.h"
  52.  
  53. #include "vecmat.h"
  54. #include "3d.h"
  55. #include "error.h"
  56. #include "mono.h"
  57. #include "mem.h"
  58. #include "args.h"
  59.  
  60. #ifndef DRIVE
  61. #include "texmap.h"
  62. #include "bm.h"
  63. #include "textures.h"
  64. #include "object.h"
  65. #include "lighting.h"
  66. #include "cfile.h"
  67. #include "piggy.h"
  68. #endif
  69.  
  70. polymodel Polygon_models[MAX_POLYGON_MODELS];   // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2};
  71.  
  72. int N_polygon_models = 0;
  73.  
  74. #define MAX_POLYGON_VECS 1000
  75. g3s_point robot_points[MAX_POLYGON_VECS];
  76.  
  77. #define PM_COMPATIBLE_VERSION 6
  78. #define PM_OBJFILE_VERSION 8
  79.  
  80. int Pof_file_end;
  81. int Pof_addr;
  82.  
  83. #define MODEL_BUF_SIZE  32768
  84.  
  85. void _pof_cfseek(int len,int type)
  86. {
  87.     switch (type) {
  88.         case SEEK_SET:  Pof_addr = len; break;
  89.         case SEEK_CUR:  Pof_addr += len;    break;
  90.         case SEEK_END:
  91.             Assert(len <= 0);   //  seeking from end, better be moving back.
  92.             Pof_addr = Pof_file_end + len;
  93.             break;
  94.     }
  95.  
  96.     if (Pof_addr > MODEL_BUF_SIZE)
  97.         Int3();
  98. }
  99.  
  100. #define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type))
  101.  
  102. int pof_read_int(ubyte *bufp)
  103. {
  104.     int i;
  105.  
  106.     i = *((int *) &bufp[Pof_addr]);
  107.     Pof_addr += 4;
  108.     return i;
  109.  
  110. //  if (cfread(&i,sizeof(i),1,f) != 1)
  111. //      Error("Unexpected end-of-file while reading object");
  112. //
  113. //  return i;
  114. }
  115.  
  116. size_t pof_cfread(void *dst, size_t elsize, size_t nelem, ubyte *bufp)
  117. {
  118.     if (Pof_addr + nelem*elsize > Pof_file_end)
  119.         return 0;
  120.  
  121.     memcpy(dst, &bufp[Pof_addr], elsize*nelem);
  122.  
  123.     Pof_addr += elsize*nelem;
  124.  
  125.     if (Pof_addr > MODEL_BUF_SIZE)
  126.         Int3();
  127.  
  128.     return nelem;
  129. }
  130.  
  131. // #define new_read_int(i,f) cfread(&(i),sizeof(i),1,(f))
  132. #define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f))
  133.  
  134. short pof_read_short(ubyte *bufp)
  135. {
  136.     short s;
  137.  
  138.     s = *((short *) &bufp[Pof_addr]);
  139.     Pof_addr += 2;
  140.     return s;
  141. //  if (cfread(&s,sizeof(s),1,f) != 1)
  142. //      Error("Unexpected end-of-file while reading object");
  143. //
  144. //  return s;
  145. }
  146.  
  147. pof_read_string(char *buf,int max, ubyte *bufp)
  148. {
  149.     int i;
  150.  
  151.     for (i=0; i<max; i++) {
  152.         if ((*buf++ = bufp[Pof_addr++]) == 0)
  153.             break;
  154.     }
  155.  
  156. //  while (max-- && (*buf=cfgetc(f)) != 0) buf++;
  157.  
  158. }
  159.  
  160. pof_read_vecs(vms_vector *vecs,int n,ubyte *bufp)
  161. {
  162. //  cfread(vecs,sizeof(vms_vector),n,f);
  163.  
  164.     memcpy(vecs, &bufp[Pof_addr], n*sizeof(*vecs));
  165.     Pof_addr += n*sizeof(*vecs);
  166.     
  167.     if (Pof_addr > MODEL_BUF_SIZE)
  168.         Int3();
  169. }
  170.  
  171. #define ID_OHDR 'RDHO'  //Object header
  172. #define ID_SOBJ 'JBOS'  //Subobject header
  173. #define ID_GUNS 'SNUG'  //List of guns on this object
  174. #define ID_ANIM 'MINA'  //Animation data
  175. #define ID_IDTA 'ATDI'  //Interpreter data
  176. #define ID_TXTR 'RTXT'  //Texture filename list
  177.  
  178. #ifdef DRIVE
  179. #define robot_info void
  180. #else
  181. vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS];
  182.  
  183. //set the animation angles for this robot.  Gun fields of robot info must
  184. //be filled in.
  185. robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]);
  186. #endif
  187.  
  188. //reads a binary file containing a 3d model
  189. polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
  190. {
  191.     CFILE *ifile;
  192.     short version;
  193.     int id,len, next_chunk;
  194.     ubyte   model_buf[MODEL_BUF_SIZE];
  195.  
  196.     if ((ifile=cfopen(filename,"rb"))==NULL) 
  197.         Error("Can't open file <%s>",filename);
  198.  
  199.     Assert(ifile->size <= MODEL_BUF_SIZE);
  200.  
  201.     Pof_addr = 0;
  202.     Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
  203.     cfclose(ifile);
  204.  
  205.     id = pof_read_int(model_buf);
  206.  
  207.     if (id!='OPSP')
  208.         Error("Bad ID in model file <%s>",filename);
  209.  
  210.     version = pof_read_short(model_buf);
  211.     
  212.     if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
  213.         Error("Bad version (%d) in model file <%s>",version,filename);
  214.  
  215.     if ( FindArg( "-bspgen" )) 
  216.         fprintf( stderr, "bspgen -c1" );
  217.  
  218.     while (new_pof_read_int(id,model_buf) == 1) {
  219.  
  220.         //id  = pof_read_int(model_buf);
  221.         len = pof_read_int(model_buf);
  222.         next_chunk = Pof_addr + len;
  223.                         
  224.         switch (id) {
  225.  
  226.             case ID_OHDR: {     //Object header
  227.                 vms_vector pmmin,pmmax;
  228.  
  229.                 //mprintf(0,"Got chunk OHDR, len=%d\n",len);
  230.  
  231.                 pm->n_models = pof_read_int(model_buf);
  232.                 pm->rad = pof_read_int(model_buf);
  233.  
  234.                 Assert(pm->n_models <= MAX_SUBMODELS);
  235.  
  236.                 pof_read_vecs(&pmmin,1,model_buf);
  237.                 pof_read_vecs(&pmmax,1,model_buf);
  238.  
  239.                 if ( FindArg( "-bspgen" ))  {
  240.                     vms_vector v;
  241.                     fix l;
  242.                 
  243.                     vm_vec_sub(&v, &pmmax, &pmmin );
  244.                     l = v.x;
  245.                     if ( v.y > l ) l = v.y;                 
  246.                     if ( v.z > l ) l = v.z;                 
  247.                                                     
  248.                     fprintf( stderr, " -l%.3f", f2fl(l) );
  249.                 }
  250.  
  251.                 break;
  252.             }
  253.             
  254.             case ID_SOBJ: {     //Subobject header
  255.                 int n;
  256.  
  257.                 //mprintf(0,"Got chunk SOBJ, len=%d\n",len);
  258.  
  259.                 n = pof_read_short(model_buf);
  260.  
  261.                 Assert(n < MAX_SUBMODELS);
  262.  
  263.                 pm->submodel_parents[n] = pof_read_short(model_buf);
  264.  
  265.                 pof_read_vecs(&pm->submodel_norms[n],1,model_buf);
  266.                 pof_read_vecs(&pm->submodel_pnts[n],1,model_buf);
  267.                 pof_read_vecs(&pm->submodel_offsets[n],1,model_buf);
  268.  
  269.                 pm->submodel_rads[n] = pof_read_int(model_buf);     //radius
  270.  
  271.                 pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset
  272.  
  273.                 break;
  274.  
  275.             }
  276.             
  277.             #ifndef DRIVE
  278.             case ID_GUNS: {     //List of guns on this object
  279.  
  280.                 //mprintf(0,"Got chunk GUNS, len=%d\n",len);
  281.  
  282.                 if (r) {
  283.                     int i;
  284.                     vms_vector gun_dir;
  285.  
  286.                     r->n_guns = pof_read_int(model_buf);
  287.  
  288.                     Assert(r->n_guns <= MAX_GUNS);
  289.  
  290.                     for (i=0;i<r->n_guns;i++) {
  291.                         int id;
  292.  
  293.                         id = pof_read_short(model_buf);
  294.                         r->gun_submodels[id] = pof_read_short(model_buf);
  295.                         Assert(r->gun_submodels[id] != 0xff);
  296.                         pof_read_vecs(&r->gun_points[id],1,model_buf);
  297.  
  298.                         if (version >= 7)
  299.                             pof_read_vecs(&gun_dir,1,model_buf);
  300.                     }
  301.                 }
  302.                 else
  303.                     pof_cfseek(model_buf,len,SEEK_CUR);
  304.  
  305.                 break;
  306.             }
  307.             
  308.             case ID_ANIM:       //Animation data
  309.                 //mprintf(0,"Got chunk ANIM, len=%d\n",len);
  310.  
  311.                 if ( FindArg( "-bspgen" ))
  312.                     fprintf( stderr, " -a" );
  313.                 
  314.                 if (r) {
  315.                     int n_frames,f,m;
  316.  
  317.                     n_frames = pof_read_short(model_buf);
  318.  
  319.                     Assert(n_frames == N_ANIM_STATES);
  320.  
  321.                     for (m=0;m<pm->n_models;m++)
  322.                         for (f=0;f<n_frames;f++)
  323.                             pof_cfread(&anim_angs[f][m],1,sizeof(vms_angvec),model_buf);
  324.  
  325.                     robot_set_angles(r,pm,anim_angs);
  326.                 
  327.                 }
  328.                 else
  329.                     pof_cfseek(model_buf,len,SEEK_CUR);
  330.  
  331.                 break;
  332.             #endif
  333.             
  334.             case ID_TXTR: {     //Texture filename list
  335.                 int n;
  336.                 char name_buf[128];
  337.  
  338.                 //mprintf(0,"Got chunk TXTR, len=%d\n",len);
  339.  
  340.                 n = pof_read_short(model_buf);
  341.                 //mprintf(0,"  num textures = %d\n",n);
  342.                 while (n--) {
  343.                     pof_read_string(name_buf,128,model_buf);
  344.                     //mprintf(0,"<%s>\n",name_buf);
  345.                 }
  346.  
  347.                 break;
  348.             }
  349.             
  350.             case ID_IDTA:       //Interpreter data
  351.                 //mprintf(0,"Got chunk IDTA, len=%d\n",len);
  352.  
  353.                 pm->model_data = malloc(len);
  354.                 pm->model_data_size = len;
  355.             
  356.                 pof_cfread(pm->model_data,1,len,model_buf);
  357.             
  358.                 break;
  359.  
  360.             default:
  361.                 //mprintf(0,"Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len);
  362.                 pof_cfseek(model_buf,len,SEEK_CUR);
  363.                 break;
  364.  
  365.         }
  366.         if ( version >= 8 )     // Version 8 needs 4-byte alignment!!!
  367.             pof_cfseek(model_buf,next_chunk,SEEK_SET);
  368.     }
  369.  
  370. //  for (i=0;i<pm->n_models;i++)
  371. //      pm->submodel_ptrs[i] += (int) pm->model_data;
  372.  
  373.     if ( FindArg( "-bspgen" )) {
  374.         char *p = strchr( filename, '.' );
  375.         *p = 0;
  376.         fprintf( stderr, " %s.3ds\n", filename );
  377.         *p = '.';
  378.     }
  379.  
  380.     return pm;
  381. }
  382.  
  383. //reads the gun information for a model
  384. //fills in arrays gun_points & gun_dirs, returns the number of guns read
  385. int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels)
  386. {
  387.     CFILE *ifile;
  388.     short version;
  389.     int id,len;
  390.     int n_guns=0;
  391.     ubyte   model_buf[MODEL_BUF_SIZE];
  392.  
  393.     if ((ifile=cfopen(filename,"rb"))==NULL) 
  394.         Error("Can't open file <%s>",filename);
  395.  
  396.     Assert(ifile->size <= MODEL_BUF_SIZE);
  397.  
  398.     Pof_addr = 0;
  399.     Pof_file_end = cfread(model_buf, 1, ifile->size, ifile);
  400.     cfclose(ifile);
  401.  
  402.     id = pof_read_int(model_buf);
  403.  
  404.     if (id!='OPSP')
  405.         Error("Bad ID in model file <%s>",filename);
  406.  
  407.     version = pof_read_short(model_buf);
  408.     
  409.     Assert(version >= 7);       //must be 7 or higher for this data
  410.  
  411.     if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
  412.         Error("Bad version (%d) in model file <%s>",version,filename);
  413.  
  414.     while (new_pof_read_int(id,model_buf) == 1) {
  415.  
  416.         //id  = pof_read_int(model_buf);
  417.         len = pof_read_int(model_buf);
  418.  
  419.         if (id == ID_GUNS) {        //List of guns on this object
  420.  
  421.             //mprintf(0,"Got chunk GUNS, len=%d\n",len);
  422.  
  423.             int i;
  424.  
  425.             n_guns = pof_read_int(model_buf);
  426.  
  427.             for (i=0;i<n_guns;i++) {
  428.                 int id,sm;
  429.  
  430.                 id = pof_read_short(model_buf);
  431.                 sm = pof_read_short(model_buf);
  432.                 if (gun_submodels)
  433.                     gun_submodels[id] = sm;
  434.                 else if (sm!=0)
  435.                     Error("Invalid gun submodel in file <%s>",filename);
  436.                 pof_read_vecs(&gun_points[id],1,model_buf);
  437.  
  438.                 pof_read_vecs(&gun_dirs[id],1,model_buf);
  439.             }
  440.  
  441.         }
  442.         else
  443.             pof_cfseek(model_buf,len,SEEK_CUR);
  444.  
  445.     }
  446.  
  447.     return n_guns;
  448. }
  449.  
  450. //free up a model, getting rid of all its memory
  451. free_model(polymodel *po)
  452. {
  453.     free(po->model_data);
  454. }
  455.  
  456. grs_bitmap *texture_list[MAX_POLYOBJ_TEXTURES];
  457. bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES];
  458.  
  459. int Simple_model_threshhold_scale=5;        //switch when this times radius far away
  460.  
  461.  
  462. //draw a polygon model
  463.  
  464. void draw_polygon_model(vms_vector *pos,vms_matrix *orient,vms_angvec *anim_angles,int model_num,int flags,fix light,fix *glow_values,bitmap_index alt_textures[])
  465. {
  466.     polymodel *po;
  467.     int i;
  468.  
  469.     Assert(model_num < N_polygon_models);
  470.  
  471.     po=&Polygon_models[model_num];
  472.  
  473.     //check if should use simple model
  474.     if (po->simpler_model )                 //must have a simpler model
  475.         if (flags==0)                           //can't switch if this is debris
  476.             //!!if (!alt_textures) {                //alternate textures might not match
  477.             //alt textures might not match, but in the one case we're using this
  478.             //for on 11/14/94, they do match.  So we leave it in.
  479.             {
  480.                 int cnt=1;
  481.                 fix depth;
  482.     
  483.                 depth = g3_calc_point_depth(pos);       //gets 3d depth
  484.  
  485.                 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
  486.                     po = &Polygon_models[po->simpler_model-1];
  487.             }
  488.  
  489.     if (alt_textures)
  490.         for (i=0;i<po->n_textures;i++)  {
  491.             texture_list_index[i] = alt_textures[i];
  492.             texture_list[i] = &GameBitmaps[alt_textures[i].index];
  493.         }
  494.     else
  495.         for (i=0;i<po->n_textures;i++)  {
  496.             texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
  497.             texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
  498.         }
  499.  
  500. #ifdef PIGGY_USE_PAGING
  501.     // Make sure the textures for this object are paged in...
  502.     piggy_page_flushed = 0;
  503.     for (i=0;i<po->n_textures;i++)  
  504.         PIGGY_PAGE_IN( texture_list_index[i] );
  505.     // Hmmm... cache got flushed in the middle of paging all these in,
  506.     // so we need to reread them all in.
  507.     if (piggy_page_flushed) {
  508.         piggy_page_flushed = 0;
  509.         for (i=0;i<po->n_textures;i++)  
  510.             PIGGY_PAGE_IN( texture_list_index[i] );
  511.     }
  512.     // Make sure that they can all fit in memory.
  513.     Assert( piggy_page_flushed == 0 );
  514. #endif
  515.  
  516.     g3_start_instance_matrix(pos,orient);
  517.  
  518.     g3_set_interp_points(robot_points);
  519.  
  520.     if (flags == 0)     //draw entire object
  521.  
  522.         g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values);
  523.  
  524.     else {
  525.         int i;
  526.     
  527.         for (i=0;flags;flags>>=1,i++)
  528.             if (flags & 1) {
  529.                 vms_vector ofs;
  530.  
  531.                 Assert(i < po->n_models);
  532.  
  533.                 //if submodel, rotate around its center point, not pivot point
  534.     
  535.                 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
  536.                 vm_vec_negate(&ofs);
  537.                 g3_start_instance_matrix(&ofs,NULL);
  538.     
  539.                 g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values);
  540.     
  541.                 g3_done_instance();
  542.             }   
  543.     }
  544.  
  545.     g3_done_instance();
  546.  
  547. }
  548.  
  549. #ifdef VIRGIN
  550. void draw_polygon_model_offset(vms_vector *pos,vms_matrix *orient,vms_angvec *anim_angles,int model_num,int flags,fix light,fix *glow_values,bitmap_index alt_textures[], fix offsetx, fix offsety)
  551. {
  552.     polymodel *po;
  553.     int i;
  554.     extern bool g3_draw_polygon_model_offset(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values, fix offsetx, fix offsety);
  555.  
  556.     Assert(model_num < N_polygon_models);
  557.  
  558.     po=&Polygon_models[model_num];
  559.  
  560.     //check if should use simple model
  561.     if (po->simpler_model )                 //must have a simpler model
  562.         if (flags==0)                           //can't switch if this is debris
  563.             //!!if (!alt_textures) {                //alternate textures might not match
  564.             //alt textures might not match, but in the one case we're using this
  565.             //for on 11/14/94, they do match.  So we leave it in.
  566.             {
  567.                 int cnt=1;
  568.                 fix depth;
  569.  
  570.                 depth = g3_calc_point_depth(pos);       //gets 3d depth
  571.  
  572.                 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
  573.                     po = &Polygon_models[po->simpler_model-1];
  574.             }
  575.  
  576.     if (alt_textures)
  577.         for (i=0;i<po->n_textures;i++)  {
  578.             texture_list_index[i] = alt_textures[i];
  579.             texture_list[i] = &GameBitmaps[alt_textures[i].index];
  580.         }
  581.     else
  582.         for (i=0;i<po->n_textures;i++)  {
  583.             texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
  584.             texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
  585.         }
  586.  
  587. #ifdef PIGGY_USE_PAGING
  588.     // Make sure the textures for this object are paged in...
  589.     piggy_page_flushed = 0;
  590.     for (i=0;i<po->n_textures;i++)
  591.         PIGGY_PAGE_IN( texture_list_index[i] );
  592.     // Hmmm... cache got flushed in the middle of paging all these in,
  593.     // so we need to reread them all in.
  594.     if (piggy_page_flushed) {
  595.         piggy_page_flushed = 0;
  596.         for (i=0;i<po->n_textures;i++)
  597.             PIGGY_PAGE_IN( texture_list_index[i] );
  598.     }
  599.     // Make sure that they can all fit in memory.
  600.     Assert( piggy_page_flushed == 0 );
  601. #endif
  602.  
  603.     g3_start_instance_matrix(pos,orient);
  604.  
  605.     g3_set_interp_points(robot_points);
  606.  
  607.     if (flags == 0)     //draw entire object
  608.  
  609.         g3_draw_polygon_model_offset(po->model_data,texture_list,anim_angles,light,glow_values, offsetx, offsety);
  610.  
  611.     else {
  612.         int i;
  613.  
  614.         for (i=0;flags;flags>>=1,i++)
  615.             if (flags & 1) {
  616.                 vms_vector ofs;
  617.  
  618.                 Assert(i < po->n_models);
  619.  
  620.                 //if submodel, rotate around its center point, not pivot point
  621.  
  622.                 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
  623.                 vm_vec_negate(&ofs);
  624.                 g3_start_instance_matrix(&ofs,NULL);
  625.  
  626.                 g3_draw_polygon_model_offset(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values, offsetx, offsety);
  627.  
  628.                 g3_done_instance();
  629.             }
  630.     }
  631.  
  632.     g3_done_instance();
  633.  
  634. }
  635.  
  636. #endif
  637.  
  638. free_polygon_models()
  639. {
  640.     int i;
  641.  
  642.     for (i=0;i<N_polygon_models;i++) {
  643.         free_model(&Polygon_models[i]);
  644.     }
  645.  
  646. }
  647.  
  648. polyobj_find_min_max(polymodel *pm)
  649. {
  650.     ushort nverts;
  651.     vms_vector *vp;
  652.     ushort *data,type;
  653.     int m;
  654.     vms_vector *big_mn,*big_mx;
  655.     
  656.     big_mn = &pm->mins;
  657.     big_mx = &pm->maxs;
  658.  
  659.     for (m=0;m<pm->n_models;m++) {
  660.         vms_vector *mn,*mx,*ofs;
  661.  
  662.         mn = &pm->submodel_mins[m];
  663.         mx = &pm->submodel_maxs[m];
  664.         ofs= &pm->submodel_offsets[m];
  665.  
  666.         data = (ushort *)&pm->model_data[pm->submodel_ptrs[m]];
  667.     
  668.         type = *data++;
  669.     
  670.         Assert(type == 7 || type == 1);
  671.     
  672.         nverts = *data++;
  673.     
  674.         if (type==7)
  675.             data+=2;        //skip start & pad
  676.     
  677.         vp = (vms_vector *) data;
  678.     
  679.         *mn = *mx = *vp++; nverts--;
  680.  
  681.         if (m==0)
  682.             *big_mn = *big_mx = *mn;
  683.     
  684.         while (nverts--) {
  685.             if (vp->x > mx->x) mx->x = vp->x;
  686.             if (vp->y > mx->y) mx->y = vp->y;
  687.             if (vp->z > mx->z) mx->z = vp->z;
  688.     
  689.             if (vp->x < mn->x) mn->x = vp->x;
  690.             if (vp->y < mn->y) mn->y = vp->y;
  691.             if (vp->z < mn->z) mn->z = vp->z;
  692.     
  693.             if (vp->x+ofs->x > big_mx->x) big_mx->x = vp->x+ofs->x;
  694.             if (vp->y+ofs->y > big_mx->y) big_mx->y = vp->y+ofs->y;
  695.             if (vp->z+ofs->z > big_mx->z) big_mx->z = vp->z+ofs->z;
  696.     
  697.             if (vp->x+ofs->x < big_mn->x) big_mn->x = vp->x+ofs->x;
  698.             if (vp->y+ofs->y < big_mn->y) big_mn->y = vp->y+ofs->y;
  699.             if (vp->z+ofs->z < big_mn->z) big_mn->z = vp->z+ofs->z;
  700.     
  701.             vp++;
  702.         }
  703.  
  704. //      printf("Submodel %d:  (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",m,mn->x,mx->x,mn->y,mx->y,mn->z,mx->z);
  705.     }
  706.  
  707. //  printf("Whole model: (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",big_mn->x,big_mx->x,big_mn->y,big_mx->y,big_mn->z,big_mx->z);
  708.  
  709. }
  710.  
  711. extern short highest_texture_num;   //from the 3d
  712.  
  713. char Pof_names[MAX_POLYGON_MODELS][13];
  714.  
  715. //returns the number of this model
  716. #ifndef DRIVE
  717. int load_polygon_model(char *filename,int n_textures,int first_texture,robot_info *r)
  718. #else
  719. int load_polygon_model(char *filename,int n_textures,grs_bitmap ***textures)
  720. #endif
  721. {
  722.     #ifdef DRIVE
  723.     #define r NULL
  724.     #endif
  725.  
  726.     Assert(N_polygon_models < MAX_POLYGON_MODELS);
  727.     Assert(n_textures < MAX_POLYOBJ_TEXTURES);
  728.  
  729.     mprintf(( 0, "Used %d/%d polygon model slots\n", N_polygon_models+1, MAX_POLYGON_MODELS ));
  730.  
  731.     Assert(strlen(filename) <= 12);
  732.     strcpy(Pof_names[N_polygon_models],filename);
  733.  
  734.     read_model_file(&Polygon_models[N_polygon_models],filename,r);
  735.  
  736.     polyobj_find_min_max(&Polygon_models[N_polygon_models]);
  737.  
  738.     g3_init_polygon_model(Polygon_models[N_polygon_models].model_data);
  739.  
  740.     if (highest_texture_num+1 != n_textures)
  741.         Error("Model <%s> references %d textures but specifies %d.",filename,highest_texture_num+1,n_textures);
  742.  
  743.     Polygon_models[N_polygon_models].n_textures = n_textures;
  744.     Polygon_models[N_polygon_models].first_texture = first_texture;
  745.     Polygon_models[N_polygon_models].simpler_model = 0;
  746.  
  747. //  Assert(polygon_models[N_polygon_models]!=NULL);
  748.  
  749.     N_polygon_models++;
  750.  
  751.     return N_polygon_models-1;
  752.  
  753. }
  754.  
  755.  
  756. void init_polygon_models()
  757. {
  758.     N_polygon_models = 0;
  759.  
  760.     atexit(free_polygon_models);
  761.  
  762. }
  763.  
  764. //compare against this size when figuring how far to place eye for picture
  765. #define BASE_MODEL_SIZE 0x28000
  766.  
  767. #define DEFAULT_VIEW_DIST 0x60000
  768.  
  769. //draws the given model in the current canvas.  The distance is set to
  770. //more-or-less fill the canvas.  Note that this routine actually renders
  771. //into an off-screen canvas that it creates, then copies to the current
  772. //canvas.
  773. void draw_model_picture(int mn,vms_angvec *orient_angles)
  774. {
  775.     vms_vector  temp_pos=ZERO_VECTOR;
  776.     vms_matrix  temp_orient = IDENTITY_MATRIX;
  777.     grs_canvas  *save_canv = grd_curcanv,*temp_canv;
  778.     //int           save_light;
  779.  
  780.     Assert(mn>=0 && mn<N_polygon_models);
  781.     #ifndef VIRGIN
  782.     temp_canv = gr_create_canvas(save_canv->cv_bitmap.bm_w,save_canv->cv_bitmap.bm_h);
  783.     gr_set_current_canvas(temp_canv);
  784.     gr_clear_canvas( BM_XRGB(0,0,0) );
  785.     #endif
  786.     g3_start_frame();
  787.     g3_set_view_matrix(&temp_pos,&temp_orient,0x9000);
  788.  
  789.     if (Polygon_models[mn].rad != 0)
  790.         temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST,Polygon_models[mn].rad,BASE_MODEL_SIZE);
  791.     else
  792.         temp_pos.z = DEFAULT_VIEW_DIST;
  793.  
  794.     vm_angles_2_matrix(&temp_orient, orient_angles);
  795.  
  796.     //save_light = Lighting_on;
  797.     //Lighting_on = 0;
  798.     #ifdef VIRGIN
  799.     draw_polygon_model_offset(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL, i2f(200), i2f(100));
  800.     #else
  801.     draw_polygon_model(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL);
  802.     #endif
  803.     //Lighting_on = save_light;
  804.     #ifndef VIRGIN
  805.     gr_set_current_canvas(save_canv);
  806.  
  807.     gr_bitmap(0,0,&temp_canv->cv_bitmap);
  808. //    printf("draw_model_picture : %d - %s\n",__LINE__, __FILE__);  // DEBUG_AUSGABE
  809.  
  810.     gr_free_canvas(temp_canv);
  811.     #endif
  812. }
  813.